#!/usr/bin/env python3
"""
智慧农业边缘控制系统 - 增强分析模块
Smart Agriculture Edge Control System - Enhanced Analytics Module

新增功能：
- 高级数据分析算法
- 智能异常检测
- 预测性维护
- 优化建议生成
"""

import numpy as np
import pandas as pd
from datetime import datetime, timedelta
from collections import defaultdict
import json
import random
import math

class EnhancedAnalytics:
    """增强分析引擎"""
    
    def __init__(self):
        self.analysis_history = []
        self.anomaly_patterns = {}
        self.optimization_rules = self._load_optimization_rules()
        self.performance_metrics = defaultdict(list)
        
    def _load_optimization_rules(self):
        """加载优化规则库"""
        return {
            'irrigation': {
                'optimal_soil_moisture': (45, 70),
                'temperature_factor': {'min': 15, 'max': 35},
                'humidity_factor': {'min': 40, 'max': 80},
                'time_windows': ['06:00-08:00', '18:00-20:00']  # 最佳灌溉时间
            },
            'nutrition': {
                'nitrogen_optimal': (20, 35),
                'phosphorus_optimal': (12, 20),
                'potassium_optimal': (25, 40),
                'ph_optimal': (6.0, 7.5)
            },
            'environment': {
                'temperature_stress': {'low': 10, 'high': 40},
                'humidity_stress': {'low': 30, 'high': 90},
                'light_minimum': 20000,
                'co2_optimal': (350, 450)
            }
        }
    
    def analyze_sensor_data(self, sensor_data, time_window='1h'):
        """分析传感器数据"""
        analysis_result = {
            'timestamp': datetime.now().isoformat(),
            'data_quality': self._assess_data_quality(sensor_data),
            'anomalies': self._detect_anomalies(sensor_data),
            'trends': self._analyze_trends(sensor_data, time_window),
            'correlations': self._analyze_correlations(sensor_data),
            'optimization_suggestions': self._generate_suggestions(sensor_data),
            'risk_assessment': self._assess_risks(sensor_data),
            'performance_score': self._calculate_performance_score(sensor_data)
        }
        
        self.analysis_history.append(analysis_result)
        self._update_performance_metrics(analysis_result)
        
        return analysis_result
    
    def _assess_data_quality(self, sensor_data):
        """评估数据质量"""
        quality_score = 100
        issues = []
        
        # 检查数据完整性
        required_sensors = ['soil_moisture', 'air_temperature', 'air_humidity', 'light_intensity']
        missing_sensors = [s for s in required_sensors if s not in sensor_data]
        if missing_sensors:
            quality_score -= len(missing_sensors) * 15
            issues.append(f"缺失传感器数据: {', '.join(missing_sensors)}")
        
        # 检查数据范围合理性
        ranges = {
            'soil_moisture': (0, 100),
            'air_temperature': (-20, 50),
            'air_humidity': (0, 100),
            'ph_value': (0, 14),
            'light_intensity': (0, 100000)
        }
        
        for sensor, (min_val, max_val) in ranges.items():
            if sensor in sensor_data:
                value = sensor_data[sensor]
                if not (min_val <= value <= max_val):
                    quality_score -= 10
                    issues.append(f"{sensor}数值异常: {value}")
        
        return {
            'score': max(0, quality_score),
            'level': 'excellent' if quality_score >= 90 else 'good' if quality_score >= 70 else 'poor',
            'issues': issues
        }
    
    def _detect_anomalies(self, sensor_data):
        """检测数据异常"""
        anomalies = []
        
        # 基于统计规则的异常检测
        statistical_anomalies = self._statistical_anomaly_detection(sensor_data)
        anomalies.extend(statistical_anomalies)
        
        # 基于农业知识的异常检测
        agricultural_anomalies = self._agricultural_anomaly_detection(sensor_data)
        anomalies.extend(agricultural_anomalies)
        
        # 时间序列异常检测
        temporal_anomalies = self._temporal_anomaly_detection(sensor_data)
        anomalies.extend(temporal_anomalies)
        
        return {
            'count': len(anomalies),
            'severity': self._calculate_anomaly_severity(anomalies),
            'details': anomalies
        }
    
    def _statistical_anomaly_detection(self, sensor_data):
        """统计异常检测"""
        anomalies = []
        
        # Z-score异常检测（简化版）
        if 'air_temperature' in sensor_data and 'air_humidity' in sensor_data:
            temp = sensor_data['air_temperature']
            humidity = sensor_data['air_humidity']
            
            # 温湿度关联性检查
            expected_humidity = 100 - (temp - 10) * 2.5
            humidity_deviation = abs(humidity - expected_humidity)
            
            if humidity_deviation > 25:
                anomalies.append({
                    'type': 'statistical',
                    'sensor': 'temperature_humidity_correlation',
                    'severity': 'medium',
                    'description': f'温湿度关联异常，偏差: {humidity_deviation:.1f}%',
                    'confidence': 0.8
                })
        
        return anomalies
    
    def _agricultural_anomaly_detection(self, sensor_data):
        """农业知识异常检测"""
        anomalies = []
        
        # 检查生长环境适宜性
        if 'soil_moisture' in sensor_data:
            moisture = sensor_data['soil_moisture']
            if moisture < 25:
                anomalies.append({
                    'type': 'agricultural',
                    'sensor': 'soil_moisture',
                    'severity': 'high',
                    'description': f'土壤湿度过低({moisture:.1f}%)，植物可能面临水分胁迫',
                    'confidence': 0.9,
                    'action': 'immediate_irrigation'
                })
            elif moisture > 85:
                anomalies.append({
                    'type': 'agricultural',
                    'sensor': 'soil_moisture',
                    'severity': 'medium',
                    'description': f'土壤湿度过高({moisture:.1f}%)，可能导致根系缺氧',
                    'confidence': 0.85,
                    'action': 'reduce_irrigation'
                })
        
        # 检查温度胁迫
        if 'air_temperature' in sensor_data:
            temp = sensor_data['air_temperature']
            if temp > 35:
                anomalies.append({
                    'type': 'agricultural',
                    'sensor': 'air_temperature',
                    'severity': 'high',
                    'description': f'温度过高({temp:.1f}°C)，植物面临热胁迫',
                    'confidence': 0.95,
                    'action': 'cooling_measures'
                })
            elif temp < 10:
                anomalies.append({
                    'type': 'agricultural',
                    'sensor': 'air_temperature',
                    'severity': 'high',
                    'description': f'温度过低({temp:.1f}°C)，植物生长受阻',
                    'confidence': 0.9,
                    'action': 'heating_measures'
                })
        
        # 检查pH值
        if 'ph_value' in sensor_data:
            ph = sensor_data['ph_value']
            if ph < 5.5 or ph > 8.0:
                severity = 'high' if ph < 5.0 or ph > 8.5 else 'medium'
                anomalies.append({
                    'type': 'agricultural',
                    'sensor': 'ph_value',
                    'severity': severity,
                    'description': f'土壤pH值异常({ph:.1f})，影响营养元素吸收',
                    'confidence': 0.9,
                    'action': 'ph_adjustment'
                })
        
        return anomalies
    
    def _temporal_anomaly_detection(self, sensor_data):
        """时间序列异常检测"""
        anomalies = []
        
        # 检查数据更新时间
        if 'timestamp' in sensor_data:
            try:
                data_time = datetime.fromisoformat(sensor_data['timestamp'].replace('Z', '+00:00'))
                current_time = datetime.now()
                time_diff = (current_time - data_time).total_seconds()
                
                if time_diff > 300:  # 5分钟无数据更新
                    anomalies.append({
                        'type': 'temporal',
                        'sensor': 'data_freshness',
                        'severity': 'medium',
                        'description': f'数据更新延迟 {time_diff/60:.1f} 分钟',
                        'confidence': 1.0,
                        'action': 'check_sensors'
                    })
            except:
                anomalies.append({
                    'type': 'temporal',
                    'sensor': 'timestamp',
                    'severity': 'low',
                    'description': '时间戳格式异常',
                    'confidence': 0.9
                })
        
        return anomalies
    
    def _analyze_trends(self, sensor_data, time_window):
        """分析数据趋势"""
        trends = {}
        
        # 模拟趋势分析（实际应用中需要历史数据）
        sensors = ['soil_moisture', 'air_temperature', 'air_humidity', 'ph_value']
        
        for sensor in sensors:
            if sensor in sensor_data:
                # 生成模拟趋势数据
                trend_data = self._generate_trend_simulation(sensor, sensor_data[sensor])
                trends[sensor] = trend_data
        
        return trends
    
    def _generate_trend_simulation(self, sensor, current_value):
        """生成趋势模拟数据"""
        trend_direction = random.choice(['increasing', 'decreasing', 'stable'])
        
        if trend_direction == 'increasing':
            slope = random.uniform(0.1, 0.5)
            prediction = current_value + slope * 6  # 6小时后预测值
        elif trend_direction == 'decreasing':
            slope = random.uniform(-0.5, -0.1)
            prediction = current_value + slope * 6
        else:
            slope = random.uniform(-0.1, 0.1)
            prediction = current_value + slope * 6
        
        return {
            'direction': trend_direction,
            'slope': slope,
            'confidence': random.uniform(0.7, 0.95),
            'prediction_6h': prediction,
            'volatility': random.choice(['low', 'medium', 'high']),
            'seasonality': random.choice(['none', 'daily', 'weekly'])
        }
    
    def _analyze_correlations(self, sensor_data):
        """分析传感器数据相关性"""
        correlations = {}
        
        # 温度-湿度相关性
        if 'air_temperature' in sensor_data and 'air_humidity' in sensor_data:
            temp = sensor_data['air_temperature']
            humidity = sensor_data['air_humidity']
            
            # 简化的相关性计算
            expected_correlation = -0.7  # 温度和湿度通常负相关
            current_correlation = self._calculate_correlation_score(temp, humidity)
            
            correlations['temperature_humidity'] = {
                'expected': expected_correlation,
                'current': current_correlation,
                'strength': abs(current_correlation),
                'status': 'normal' if abs(current_correlation - expected_correlation) < 0.3 else 'unusual'
            }
        
        # 土壤湿度-温度相关性
        if 'soil_moisture' in sensor_data and 'air_temperature' in sensor_data:
            correlations['moisture_temperature'] = {
                'expected': -0.4,
                'current': random.uniform(-0.6, -0.2),
                'strength': random.uniform(0.3, 0.6),
                'status': random.choice(['normal', 'unusual'])
            }
        
        return correlations
    
    def _calculate_correlation_score(self, value1, value2):
        """计算相关性分数（简化版）"""
        # 这是一个简化的实现，实际需要历史数据序列
        normalized_diff = abs(value1 - value2) / 100
        return -0.7 + random.uniform(-0.2, 0.2) * normalized_diff
    
    def _generate_suggestions(self, sensor_data):
        """生成优化建议"""
        suggestions = []
        
        # 基于优化规则生成建议
        irrigation_suggestions = self._generate_irrigation_suggestions(sensor_data)
        suggestions.extend(irrigation_suggestions)
        
        nutrition_suggestions = self._generate_nutrition_suggestions(sensor_data)
        suggestions.extend(nutrition_suggestions)
        
        environment_suggestions = self._generate_environment_suggestions(sensor_data)
        suggestions.extend(environment_suggestions)
        
        # 按优先级排序
        suggestions.sort(key=lambda x: x['priority'], reverse=True)
        
        return suggestions[:10]  # 返回前10个建议
    
    def _generate_irrigation_suggestions(self, sensor_data):
        """生成灌溉建议"""
        suggestions = []
        
        if 'soil_moisture' in sensor_data:
            moisture = sensor_data['soil_moisture']
            optimal_range = self.optimization_rules['irrigation']['optimal_soil_moisture']
            
            if moisture < optimal_range[0]:
                suggestions.append({
                    'category': 'irrigation',
                    'type': 'action',
                    'priority': 9,
                    'title': '启动灌溉系统',
                    'description': f'土壤湿度({moisture:.1f}%)低于最佳范围，建议立即灌溉',
                    'action': 'start_irrigation',
                    'estimated_impact': 'high',
                    'confidence': 0.95
                })
            elif moisture > optimal_range[1]:
                suggestions.append({
                    'category': 'irrigation',
                    'type': 'warning',
                    'priority': 6,
                    'title': '暂停灌溉',
                    'description': f'土壤湿度({moisture:.1f}%)过高，建议暂停灌溉',
                    'action': 'stop_irrigation',
                    'estimated_impact': 'medium',
                    'confidence': 0.9
                })
        
        return suggestions
    
    def _generate_nutrition_suggestions(self, sensor_data):
        """生成营养管理建议"""
        suggestions = []
        
        nutrients = ['nitrogen', 'phosphorus', 'potassium']
        for nutrient in nutrients:
            if nutrient in sensor_data:
                value = sensor_data[nutrient]
                optimal_range = self.optimization_rules['nutrition'][f'{nutrient}_optimal']
                
                if value < optimal_range[0]:
                    suggestions.append({
                        'category': 'nutrition',
                        'type': 'action',
                        'priority': 7,
                        'title': f'补充{nutrient}',
                        'description': f'{nutrient}含量({value:.1f})偏低，建议补充营养液',
                        'action': f'add_{nutrient}',
                        'estimated_impact': 'medium',
                        'confidence': 0.85
                    })
        
        if 'ph_value' in sensor_data:
            ph = sensor_data['ph_value']
            optimal_range = self.optimization_rules['nutrition']['ph_optimal']
            
            if ph < optimal_range[0]:
                suggestions.append({
                    'category': 'nutrition',
                    'type': 'action',
                    'priority': 8,
                    'title': 'pH值调节',
                    'description': f'土壤pH值({ph:.1f})偏酸，建议添加石灰调节',
                    'action': 'increase_ph',
                    'estimated_impact': 'high',
                    'confidence': 0.9
                })
            elif ph > optimal_range[1]:
                suggestions.append({
                    'category': 'nutrition',
                    'type': 'action',
                    'priority': 8,
                    'title': 'pH值调节',
                    'description': f'土壤pH值({ph:.1f})偏碱，建议添加酸性调节剂',
                    'action': 'decrease_ph',
                    'estimated_impact': 'high',
                    'confidence': 0.9
                })
        
        return suggestions
    
    def _generate_environment_suggestions(self, sensor_data):
        """生成环境管理建议"""
        suggestions = []
        
        if 'air_temperature' in sensor_data:
            temp = sensor_data['air_temperature']
            stress_limits = self.optimization_rules['environment']['temperature_stress']
            
            if temp > stress_limits['high']:
                suggestions.append({
                    'category': 'environment',
                    'type': 'urgent',
                    'priority': 10,
                    'title': '温度控制',
                    'description': f'温度({temp:.1f}°C)过高，建议开启降温系统',
                    'action': 'activate_cooling',
                    'estimated_impact': 'high',
                    'confidence': 0.95
                })
            elif temp < stress_limits['low']:
                suggestions.append({
                    'category': 'environment',
                    'type': 'urgent',
                    'priority': 10,
                    'title': '温度控制',
                    'description': f'温度({temp:.1f}°C)过低，建议开启加热系统',
                    'action': 'activate_heating',
                    'estimated_impact': 'high',
                    'confidence': 0.95
                })
        
        if 'light_intensity' in sensor_data:
            light = sensor_data['light_intensity']
            min_light = self.optimization_rules['environment']['light_minimum']
            
            if light < min_light:
                suggestions.append({
                    'category': 'environment',
                    'type': 'action',
                    'priority': 6,
                    'title': '补充光照',
                    'description': f'光照强度({light:.0f})不足，建议开启补光灯',
                    'action': 'supplement_lighting',
                    'estimated_impact': 'medium',
                    'confidence': 0.8
                })
        
        return suggestions
    
    def _assess_risks(self, sensor_data):
        """评估风险等级"""
        risks = {
            'overall_level': 'low',
            'categories': {
                'crop_health': {'level': 'low', 'factors': []},
                'equipment': {'level': 'low', 'factors': []},
                'environment': {'level': 'low', 'factors': []},
                'yield': {'level': 'low', 'factors': []}
            },
            'urgent_actions': []
        }
        
        # 作物健康风险
        if 'soil_moisture' in sensor_data:
            moisture = sensor_data['soil_moisture']
            if moisture < 25:
                risks['categories']['crop_health']['level'] = 'high'
                risks['categories']['crop_health']['factors'].append('土壤湿度严重不足')
                risks['urgent_actions'].append('立即启动灌溉系统')
        
        # 环境风险
        if 'air_temperature' in sensor_data:
            temp = sensor_data['air_temperature']
            if temp > 40 or temp < 5:
                risks['categories']['environment']['level'] = 'high'
                risks['categories']['environment']['factors'].append('极端温度条件')
                risks['urgent_actions'].append('启动温度调节系统')
        
        # 计算总体风险等级
        risk_levels = [info['level'] for info in risks['categories'].values()]
        if 'high' in risk_levels:
            risks['overall_level'] = 'high'
        elif 'medium' in risk_levels:
            risks['overall_level'] = 'medium'
        
        return risks
    
    def _calculate_performance_score(self, sensor_data):
        """计算系统性能分数"""
        scores = {
            'environment_quality': 0,
            'resource_efficiency': 0,
            'growth_conditions': 0,
            'system_health': 0
        }
        
        # 环境质量评分
        if all(k in sensor_data for k in ['air_temperature', 'air_humidity', 'light_intensity']):
            temp_score = self._score_temperature(sensor_data['air_temperature'])
            humidity_score = self._score_humidity(sensor_data['air_humidity'])
            light_score = self._score_light(sensor_data['light_intensity'])
            scores['environment_quality'] = (temp_score + humidity_score + light_score) / 3
        
        # 资源效率评分
        if 'soil_moisture' in sensor_data:
            scores['resource_efficiency'] = self._score_irrigation_efficiency(sensor_data['soil_moisture'])
        
        # 生长条件评分
        if all(k in sensor_data for k in ['ph_value', 'nitrogen', 'phosphorus', 'potassium']):
            ph_score = self._score_ph(sensor_data['ph_value'])
            nutrition_score = self._score_nutrition(sensor_data)
            scores['growth_conditions'] = (ph_score + nutrition_score) / 2
        
        # 系统健康评分
        scores['system_health'] = random.uniform(0.85, 0.98)  # 模拟系统健康度
        
        # 计算总分
        overall_score = sum(scores.values()) / len(scores)
        
        return {
            'overall': overall_score,
            'categories': scores,
            'grade': self._get_performance_grade(overall_score),
            'improvement_potential': max(0, 1 - overall_score)
        }
    
    def _score_temperature(self, temperature):
        """温度评分"""
        optimal_range = (20, 28)
        if optimal_range[0] <= temperature <= optimal_range[1]:
            return 1.0
        elif 15 <= temperature <= 35:
            deviation = min(abs(temperature - optimal_range[0]), abs(temperature - optimal_range[1]))
            return max(0.5, 1 - deviation / 10)
        else:
            return 0.2
    
    def _score_humidity(self, humidity):
        """湿度评分"""
        optimal_range = (50, 70)
        if optimal_range[0] <= humidity <= optimal_range[1]:
            return 1.0
        elif 40 <= humidity <= 80:
            deviation = min(abs(humidity - optimal_range[0]), abs(humidity - optimal_range[1]))
            return max(0.5, 1 - deviation / 20)
        else:
            return 0.3
    
    def _score_light(self, light_intensity):
        """光照评分"""
        if light_intensity >= 40000:
            return 1.0
        elif light_intensity >= 20000:
            return 0.8
        elif light_intensity >= 10000:
            return 0.5
        else:
            return 0.2
    
    def _score_irrigation_efficiency(self, soil_moisture):
        """灌溉效率评分"""
        optimal_range = (45, 70)
        if optimal_range[0] <= soil_moisture <= optimal_range[1]:
            return 1.0
        elif 30 <= soil_moisture <= 80:
            deviation = min(abs(soil_moisture - optimal_range[0]), abs(soil_moisture - optimal_range[1]))
            return max(0.4, 1 - deviation / 25)
        else:
            return 0.2
    
    def _score_ph(self, ph_value):
        """pH评分"""
        optimal_range = (6.0, 7.5)
        if optimal_range[0] <= ph_value <= optimal_range[1]:
            return 1.0
        elif 5.5 <= ph_value <= 8.0:
            deviation = min(abs(ph_value - optimal_range[0]), abs(ph_value - optimal_range[1]))
            return max(0.5, 1 - deviation / 2)
        else:
            return 0.3
    
    def _score_nutrition(self, sensor_data):
        """营养评分"""
        nutrition_score = 0
        count = 0
        
        nutrients = {
            'nitrogen': (20, 35),
            'phosphorus': (12, 20),
            'potassium': (25, 40)
        }
        
        for nutrient, (min_val, max_val) in nutrients.items():
            if nutrient in sensor_data:
                value = sensor_data[nutrient]
                if min_val <= value <= max_val:
                    nutrition_score += 1.0
                elif value >= min_val * 0.7 and value <= max_val * 1.3:
                    nutrition_score += 0.6
                else:
                    nutrition_score += 0.3
                count += 1
        
        return nutrition_score / count if count > 0 else 0.5
    
    def _get_performance_grade(self, score):
        """获取性能等级"""
        if score >= 0.9:
            return 'A+'
        elif score >= 0.8:
            return 'A'
        elif score >= 0.7:
            return 'B+'
        elif score >= 0.6:
            return 'B'
        elif score >= 0.5:
            return 'C'
        else:
            return 'D'
    
    def _calculate_anomaly_severity(self, anomalies):
        """计算异常严重程度"""
        if not anomalies:
            return 'none'
        
        severity_counts = {'low': 0, 'medium': 0, 'high': 0}
        for anomaly in anomalies:
            severity = anomaly.get('severity', 'low')
            severity_counts[severity] += 1
        
        if severity_counts['high'] > 0:
            return 'critical'
        elif severity_counts['medium'] > 2:
            return 'high'
        elif severity_counts['medium'] > 0:
            return 'medium'
        else:
            return 'low'
    
    def _update_performance_metrics(self, analysis_result):
        """更新性能指标"""
        score = analysis_result['performance_score']['overall']
        self.performance_metrics['scores'].append(score)
        
        # 保持最近100个记录
        if len(self.performance_metrics['scores']) > 100:
            self.performance_metrics['scores'] = self.performance_metrics['scores'][-100:]
    
    def get_system_health_report(self):
        """获取系统健康报告"""
        if not self.performance_metrics['scores']:
            return {'status': 'insufficient_data'}
        
        scores = self.performance_metrics['scores']
        avg_score = sum(scores) / len(scores)
        trend = 'improving' if scores[-1] > avg_score else 'declining' if scores[-1] < avg_score else 'stable'
        
        return {
            'average_performance': avg_score,
            'current_performance': scores[-1],
            'trend': trend,
            'stability': 'high' if max(scores) - min(scores) < 0.2 else 'medium' if max(scores) - min(scores) < 0.4 else 'low',
            'recommendation': self._get_health_recommendation(avg_score, trend)
        }
    
    def _get_health_recommendation(self, avg_score, trend):
        """获取健康建议"""
        if avg_score >= 0.8 and trend == 'improving':
            return "系统运行优良，继续保持当前管理策略"
        elif avg_score >= 0.6 and trend == 'stable':
            return "系统运行正常，可考虑优化措施提升性能"
        elif trend == 'declining':
            return "系统性能下降，建议检查设备状态和环境条件"
        else:
            return "系统需要关注，建议进行全面检查和优化"

def main():
    """测试分析模块"""
    analytics = EnhancedAnalytics()
    
    # 模拟传感器数据
    test_data = {
        'soil_moisture': 35.5,
        'air_temperature': 28.3,
        'air_humidity': 65.2,
        'light_intensity': 45000,
        'ph_value': 6.9,
        'nitrogen': 22.1,
        'phosphorus': 14.5,
        'potassium': 28.7,
        'timestamp': datetime.now().isoformat()
    }
    
    # 执行分析
    result = analytics.analyze_sensor_data(test_data)
    
    print("=== 智慧农业数据分析报告 ===")
    print(f"数据质量: {result['data_quality']['level']} ({result['data_quality']['score']}/100)")
    print(f"异常检测: {result['anomalies']['count']} 个异常 (严重程度: {result['anomalies']['severity']})")
    print(f"优化建议: {len(result['optimization_suggestions'])} 条建议")
    print(f"性能评分: {result['performance_score']['grade']} ({result['performance_score']['overall']:.2f})")
    
    if result['optimization_suggestions']:
        print("\n主要建议:")
        for suggestion in result['optimization_suggestions'][:3]:
            print(f"- {suggestion['title']}: {suggestion['description']}")

if __name__ == "__main__":
    main()